﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Brain;
using System.Diagnostics;

namespace Brain.Photon
{
#if !WINDOWS_PHONE
    internal struct PhotonParticleGPU
    {
        public Vector4 PositionTime;
        public Vector4 LinearVelocitySize;
        public Vector4 StartColor;
    }
#endif
    /// <summary>
    /// The Main GPU Renderer of Photon. Does most(MOST) calculation on the CPU rather than on the GPU. Doesn't work on Windows Phone 7
    /// </summary>
#if !WINDOWS_PHONE
    public class PhotonMainGPURenderer : PhotonRenderer
    {
        /// <summary>
        /// Responsible for help Rendering the Particles as Instanced Planes
        /// </summary>
        public InstancingSystem InstancingHelper;

        /// <summary>
        /// The Graphics Device used
        /// </summary>
        public GraphicsDevice GraphicsDevice;

        /// <summary>
        /// The Depth Stencil State to use while Rendering
        /// </summary>
        public DepthStencilState DepthStencilState;

#if !SILVERLIGHT
        /// <summary>
        /// The Effect used to draw the particles
        /// </summary>
        internal Effect Effect;
#else
        internal SilverlightEffect Effect;
#endif

        /// <summary>
        /// The Rasterizer State used while Rendering
        /// </summary>
        public RasterizerState RasterizerState = RasterizerState.CullNone;

        public bool AlphaClip = false;
        
        /// <summary>
        /// Stufff
        /// </summary>
        internal static VertexDeclaration instanceVertexDeclaration = new VertexDeclaration
        (
            new VertexElement(0, VertexElementFormat.Vector4, VertexElementUsage.Fog, 0),
            new VertexElement(16, VertexElementFormat.Vector4, VertexElementUsage.Fog, 1),
            new VertexElement(32, VertexElementFormat.Vector4, VertexElementUsage.Fog, 2)
        );

#if XBOX
        Byte[] effectBytes = new Byte[3328] {188,240,11,207,0,0,0,16,0,0,0,0,0,0,0,1,254,255,9,1,0,0,4,68,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,44,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,71,114,97,118,105,116,121,0,0,0,0,3,0,0,0,0,0,0,0,88,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,12,67,117,114,114,101,110,116,84,105,109,101,0,0,0,0,3,0,0,0,1,0,0,0,148,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,69,110,100,67,111,108,111,114,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,208,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,83,116,97,114,116,67,111,108,111,114,0,0,0,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,14,83,116,97,114,116,70,97,100,101,84,105,109,101,0,0,0,0,0,0,3,0,0,0,0,0,0,1,52,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,8,77,97,120,84,105,109,101,0,0,0,0,3,0,0,0,0,0,0,1,96,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,19,82,97,110,103,101,70,114,111,109,70,97,100,101,84,111,69,110,100,0,0,0,0,0,3,0,0,0,1,0,0,1,160,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,76,105,110,101,97,114,86,101,108,111,99,105,116,121,76,111,115,115,0,0,0,0,0,3,0,0,0,0,0,0,1,216,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,19,84,105,109,101,84,111,68,101,102,97,117,108,116,67,111,108,111,114,0,0,0,0,0,3,0,0,0,3,0,0,2,76,0,0,2,88,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,87,111,114,108,100,0,0,0,0,0,0,6,87,79,82,76,68,0,0,0,0,0,0,1,0,0,0,0,0,0,2,132,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,10,65,108,112,104,97,67,108,105,112,0,0,0,0,0,0,3,0,0,0,3,0,0,2,240,0,0,2,252,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,86,105,101,119,0,0,0,0,0,0,0,5,86,73,69,87,0,0,0,0,0,0,0,3,0,0,0,3,0,0,3,100,0,0,3,116,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,80,114,111,106,101,99,116,105,111,110,0,0,0,0,0,11,80,82,79,74,69,67,84,73,79,78,0,0,0,0,0,5,0,0,0,4,0,0,3,156,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,84,101,120,116,117,114,101,0,0,0,0,12,0,0,0,4,0,0,3,232,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,5,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,110,0,0,0,16,0,0,3,192,0,0,3,188,0,0,0,15,84,101,120,116,117,114,101,83,97,109,112,108,101,114,0,0,0,0,0,3,0,0,0,16,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,15,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,80,97,115,115,49,0,0,0,0,0,0,5,80,105,99,107,0,0,0,0,0,0,0,15,0,0,0,1,0,0,0,4,0,0,0,5,0,0,0,4,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,84,0,0,0,0,0,0,0,0,0,0,0,104,0,0,0,132,0,0,0,0,0,0,0,0,0,0,0,164,0,0,0,192,0,0,0,0,0,0,0,0,0,0,0,224,0,0,0,252,0,0,0,0,0,0,0,0,0,0,1,20,0,0,1,48,0,0,0,0,0,0,0,0,0,0,1,64,0,0,1,92,0,0,0,0,0,0,0,0,0,0,1,120,0,0,1,148,0,0,0,0,0,0,0,0,0,0,1,184,0,0,1,212,0,0,0,0,0,0,0,0,0,0,1,240,0,0,2,12,0,0,0,0,0,0,0,0,0,0,2,100,0,0,2,128,0,0,0,0,0,0,0,0,0,0,2,148,0,0,2,176,0,0,0,0,0,0,0,0,0,0,3,8,0,0,3,36,0,0,0,0,0,0,0,0,0,0,3,132,0,0,3,152,0,0,0,0,0,0,0,0,0,0,3,168,0,0,3,212,0,0,0,0,0,0,0,0,0,0,4,56,0,0,0,0,0,0,0,1,0,0,4,44,0,0,0,0,0,0,0,2,0,0,0,92,0,0,0,0,0,0,4,0,0,0,3,252,0,0,0,93,0,0,0,0,0,0,4,24,0,0,4,20,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,1,0,0,0,0,0,0,1,188,16,42,17,0,0,0,1,28,0,0,0,160,0,0,0,0,0,0,0,36,0,0,0,204,0,0,0,244,0,0,0,0,0,0,0,0,0,0,0,164,0,0,0,28,0,0,0,151,255,255,3,0,0,0,0,2,0,0,0,28,0,0,0,0,0,0,0,144,0,0,0,68,0,0,0,0,0,1,0,0,0,0,0,80,0,0,0,96,0,0,0,112,0,3,0,0,0,1,0,0,0,0,0,128,0,0,0,0,65,108,112,104,97,67,108,105,112,0,171,171,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,101,120,116,117,114,101,83,97,109,112,108,101,114,0,171,0,4,0,12,0,1,0,1,0,1,0,0,0,0,0,0,112,115,95,51,95,48,0,50,46,48,46,49,49,54,50,54,46,48,0,171,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,20,1,252,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,96,16,0,2,0,0,0,0,8,0,2,0,0,0,0,24,66,0,1,0,3,0,0,0,33,0,0,48,80,0,0,241,160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,16,3,0,0,18,0,196,0,0,0,0,0,0,4,32,4,178,0,18,0,0,0,0,0,16,6,0,0,34,0,0,0,0,0,16,8,0,1,31,31,244,88,0,0,64,0,184,16,2,0,1,0,0,65,194,0,0,255,200,0,0,0,0,177,108,0,121,255,2,0,200,15,128,0,0,148,0,0,225,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,5,80,16,42,17,1,0,0,2,244,0,0,2,92,0,0,0,0,0,0,0,36,0,0,2,128,0,0,2,168,0,0,0,0,0,0,0,0,0,0,2,88,0,0,0,28,0,0,2,75,255,254,3,0,0,0,0,11,0,0,0,28,0,0,0,0,0,0,2,68,0,0,0,248,0,2,0,1,0,1,0,0,0,0,1,4,0,0,1,20,0,0,1,36,0,2,0,2,0,1,0,0,0,0,1,48,0,0,1,20,0,0,1,64,0,2,0,0,0,1,0,0,0,0,1,72,0,0,1,20,0,0,1,88,0,2,0,7,0,1,0,0,0,0,1,72,0,0,1,20,0,0,1,107,0,2,0,5,0,1,0,0,0,0,1,4,0,0,1,20,0,0,1,115,0,2,0,12,0,4,0,0,0,0,1,128,0,0,1,144,0,0,1,208,0,2,0,6,0,1,0,0,0,0,1,4,0,0,1,20,0,0,1,227,0,2,0,3,0,1,0,0,0,0,1,48,0,0,1,20,0,0,1,238,0,2,0,4,0,1,0,0,0,0,1,4,0,0,1,20,0,0,1,252,0,2,0,8,0,1,0,0,0,0,1,4,0,0,1,20,0,0,2,15,0,2,0,9,0,3,0,0,0,0,1,128,0,0,2,20,67,117,114,114,101,110,116,84,105,109,101,0,0,0,0,3,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,110,100,67,111,108,111,114,0,171,171,171,0,1,0,3,0,1,0,4,0,1,0,0,0,0,0,0,71,114,97,118,105,116,121,0,0,1,0,3,0,1,0,3,0,1,0,0,0,0,0,0,76,105,110,101,97,114,86,101,108,111,99,105,116,121,76,111,115,115,0,77,97,120,84,105,109,101,0,80,114,111,106,101,99,116,105,111,110,0,171,171,0,3,0,3,0,4,0,4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,97,110,103,101,70,114,111,109,70,97,100,101,84,111,69,110,100,0,83,116,97,114,116,67,111,108,111,114,0,83,116,97,114,116,70,97,100,101,84,105,109,101,0,84,105,109,101,84,111,68,101,102,97,117,108,116,67,111,108,111,114,0,86,105,101,119,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,118,115,95,51,95,48,0,50,46,48,46,49,49,54,50,54,46,48,0,171,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,20,0,252,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,2,28,0,17,0,7,0,0,0,0,0,0,0,0,0,0,24,66,0,0,0,1,0,0,0,5,0,0,0,2,0,0,2,144,0,16,0,5,0,0,80,6,0,0,176,7,0,1,176,8,0,34,176,9,0,0,48,80,0,1,241,160,0,0,16,42,0,0,16,43,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,63,128,0,0,63,0,0,0,0,0,0,0,249,85,96,5,96,11,18,1,16,0,0,0,0,0,96,17,96,23,18,0,16,0,0,0,0,0,64,29,0,0,86,0,194,0,0,0,0,0,96,33,48,39,18,0,18,0,0,0,0,0,0,0,32,42,196,0,34,0,0,0,5,248,32,0,0,0,14,136,0,0,0,0,5,248,64,0,0,0,15,200,0,0,0,0,5,248,96,0,0,0,6,136,0,0,0,0,5,248,16,0,0,0,6,17,0,0,0,0,5,248,48,0,0,0,6,136,0,0,0,0,76,131,5,0,0,178,108,108,1,0,5,5,20,38,0,5,0,188,27,27,225,0,5,6,184,79,0,3,0,0,0,65,129,3,3,1,200,7,0,7,0,198,98,180,235,0,1,6,200,1,0,0,0,198,108,0,166,0,4,0,8,24,5,2,0,108,108,198,116,255,0,0,200,11,0,0,0,180,111,0,225,5,5,0,20,46,0,6,0,81,198,198,161,0,255,1,168,17,5,0,0,27,108,65,129,6,5,7,172,33,5,6,0,108,108,193,129,0,0,7,172,75,5,0,0,180,192,128,192,7,6,7,200,11,0,0,4,180,198,16,235,5,0,0,200,4,0,4,24,108,198,0,101,8,0,0,112,0,0,0,24,0,0,198,226,0,0,4,184,64,0,0,24,0,0,66,194,0,0,8,76,68,0,4,28,198,108,108,128,0,8,8,200,4,0,0,24,198,198,0,225,4,0,0,200,15,0,3,24,0,198,0,225,3,0,0,124,128,2,0,0,0,0,27,226,0,0,2,76,72,0,2,26,198,108,108,128,0,5,6,200,4,0,0,24,27,198,177,203,2,0,255,200,15,0,5,28,0,0,0,160,3,2,0,200,15,0,3,24,0,198,0,235,5,0,3,200,15,0,5,0,172,191,177,76,255,0,255,200,1,0,0,0,62,0,0,111,11,5,0,200,2,0,0,0,62,0,0,111,10,5,0,36,132,0,0,0,62,0,108,111,9,5,128,200,7,0,0,0,98,27,192,235,2,1,0,200,1,128,62,0,62,52,0,111,12,0,0,200,2,128,62,0,62,52,0,111,13,0,0,200,4,128,62,0,62,52,0,111,14,0,0,200,8,128,62,0,62,52,0,111,15,0,0,200,3,128,0,0,176,176,0,226,4,4,0,200,15,128,1,0,0,0,0,226,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,84,101,120,116,117,114,101,0 };
#endif
#if WINDOWS
        Byte[] effectBytes = new Byte[3696] {207,11,240,188,16,0,0,0,0,0,0,0,1,0,0,0,1,9,255,254,68,4,0,0,0,0,0,0,3,0,0,0,1,0,0,0,44,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,71,114,97,118,105,116,121,0,3,0,0,0,0,0,0,0,88,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,12,0,0,0,67,117,114,114,101,110,116,84,105,109,101,0,3,0,0,0,1,0,0,0,148,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,69,110,100,67,111,108,111,114,0,240,173,186,3,0,0,0,1,0,0,0,208,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,83,116,97,114,116,67,111,108,111,114,0,186,3,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,14,0,0,0,83,116,97,114,116,70,97,100,101,84,105,109,101,0,173,186,3,0,0,0,0,0,0,0,52,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,8,0,0,0,77,97,120,84,105,109,101,0,3,0,0,0,0,0,0,0,96,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,19,0,0,0,82,97,110,103,101,70,114,111,109,70,97,100,101,84,111,69,110,100,0,186,3,0,0,0,1,0,0,0,160,1,0,0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,76,105,110,101,97,114,86,101,108,111,99,105,116,121,76,111,115,115,0,186,3,0,0,0,0,0,0,0,216,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,19,0,0,0,84,105,109,101,84,111,68,101,102,97,117,108,116,67,111,108,111,114,0,186,3,0,0,0,2,0,0,0,76,2,0,0,88,2,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,87,111,114,108,100,0,173,186,6,0,0,0,87,79,82,76,68,0,173,186,1,0,0,0,0,0,0,0,132,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,10,0,0,0,65,108,112,104,97,67,108,105,112,0,173,186,3,0,0,0,2,0,0,0,240,2,0,0,252,2,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,86,105,101,119,0,240,173,186,5,0,0,0,86,73,69,87,0,240,173,186,3,0,0,0,2,0,0,0,100,3,0,0,116,3,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,80,114,111,106,101,99,116,105,111,110,0,186,11,0,0,0,80,82,79,74,69,67,84,73,79,78,0,186,5,0,0,0,4,0,0,0,156,3,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,0,0,0,84,101,120,116,117,114,101,0,12,0,0,0,4,0,0,0,232,3,0,0,0,0,0,0,0,0,0,0,2,0,0,0,5,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,164,0,0,0,0,1,0,0,192,3,0,0,188,3,0,0,15,0,0,0,84,101,120,116,117,114,101,83,97,109,112,108,101,114,0,186,3,0,0,0,16,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,15,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,80,97,115,115,49,0,173,186,5,0,0,0,80,105,99,107,0,240,173,186,15,0,0,0,1,0,0,0,4,0,0,0,5,0,0,0,4,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,84,0,0,0,0,0,0,0,0,0,0,0,104,0,0,0,132,0,0,0,0,0,0,0,0,0,0,0,164,0,0,0,192,0,0,0,0,0,0,0,0,0,0,0,224,0,0,0,252,0,0,0,0,0,0,0,0,0,0,0,20,1,0,0,48,1,0,0,0,0,0,0,0,0,0,0,64,1,0,0,92,1,0,0,0,0,0,0,0,0,0,0,120,1,0,0,148,1,0,0,0,0,0,0,0,0,0,0,184,1,0,0,212,1,0,0,0,0,0,0,0,0,0,0,240,1,0,0,12,2,0,0,0,0,0,0,0,0,0,0,100,2,0,0,128,2,0,0,0,0,0,0,0,0,0,0,148,2,0,0,176,2,0,0,0,0,0,0,0,0,0,0,8,3,0,0,36,3,0,0,0,0,0,0,0,0,0,0,132,3,0,0,152,3,0,0,0,0,0,0,0,0,0,0,168,3,0,0,212,3,0,0,0,0,0,0,0,0,0,0,56,4,0,0,0,0,0,0,1,0,0,0,44,4,0,0,0,0,0,0,2,0,0,0,146,0,0,0,0,0,0,0,0,4,0,0,252,3,0,0,147,0,0,0,0,0,0,0,24,4,0,0,20,4,0,0,1,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,1,0,0,0,0,0,0,0,92,1,0,0,0,3,255,255,254,255,51,0,67,84,65,66,28,0,0,0,151,0,0,0,0,3,255,255,2,0,0,0,28,0,0,0,0,0,0,32,144,0,0,0,68,0,0,0,2,0,0,0,1,0,0,0,80,0,0,0,96,0,0,0,112,0,0,0,3,0,0,0,1,0,0,0,128,0,0,0,0,0,0,0,65,108,112,104,97,67,108,105,112,0,171,171,0,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,101,120,116,117,114,101,83,97,109,112,108,101,114,0,171,4,0,12,0,1,0,1,0,1,0,0,0,0,0,0,0,112,115,95,51,95,48,0,77,105,99,114,111,115,111,102,116,32,40,82,41,32,72,76,83,76,32,83,104,97,100,101,114,32,67,111,109,112,105,108,101,114,32,57,46,50,54,46,57,53,50,46,50,56,52,52,0,81,0,0,5,1,0,15,160,0,0,0,191,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,2,5,0,0,128,0,0,3,144,31,0,0,2,10,0,0,128,1,0,15,144,31,0,0,2,0,0,0,144,0,8,15,160,66,0,0,3,0,0,15,128,0,0,228,144,0,8,228,160,2,0,0,3,1,0,1,128,0,0,255,128,1,0,0,160,5,0,0,3,0,8,15,128,0,0,228,128,1,0,228,144,5,0,0,3,0,0,15,128,1,0,0,128,0,0,0,160,65,0,0,1,0,0,15,128,255,255,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,32,7,0,0,0,3,254,255,254,255,132,0,67,84,65,66,28,0,0,0,216,1,0,0,0,3,254,255,9,0,0,0,28,0,0,0,0,0,0,32,209,1,0,0,208,0,0,0,2,0,10,0,1,0,0,0,220,0,0,0,236,0,0,0,252,0,0,0,2,0,11,0,1,0,0,0,8,1,0,0,236,0,0,0,24,1,0,0,2,0,15,0,1,0,0,0,44,1,0,0,236,0,0,0,60,1,0,0,2,0,14,0,1,0,0,0,220,0,0,0,236,0,0,0,68,1,0,0,2,0,0,0,4,0,0,0,80,1,0,0,96,1,0,0,160,1,0,0,2,0,12,0,1,0,0,0,8,1,0,0,236,0,0,0,171,1,0,0,2,0,13,0,1,0,0,0,220,0,0,0,236,0,0,0,185,1,0,0,2,0,16,0,1,0,0,0,220,0,0,0,236,0,0,0,204,1,0,0,2,0,4,0,3,0,0,0,80,1,0,0,96,1,0,0,67,117,114,114,101,110,116,84,105,109,101,0,0,0,3,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,110,100,67,111,108,111,114,0,171,171,171,1,0,3,0,1,0,4,0,1,0,0,0,0,0,0,0,76,105,110,101,97,114,86,101,108,111,99,105,116,121,76,111,115,115,0,171,1,0,3,0,1,0,3,0,1,0,0,0,0,0,0,0,77,97,120,84,105,109,101,0,80,114,111,106,101,99,116,105,111,110,0,171,3,0,3,0,4,0,4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,116,97,114,116,67,111,108,111,114,0,83,116,97,114,116,70,97,100,101,84,105,109,101,0,84,105,109,101,84,111,68,101,102,97,117,108,116,67,111,108,111,114,0,86,105,101,119,0,118,115,95,51,95,48,0,77,105,99,114,111,115,111,102,116,32,40,82,41,32,72,76,83,76,32,83,104,97,100,101,114,32,67,111,109,112,105,108,101,114,32,57,46,50,54,46,57,53,50,46,50,56,52,52,0,171,171,171,254,255,146,0,80,82,69,83,1,2,88,70,254,255,75,0,67,84,65,66,28,0,0,0,247,0,0,0,1,2,88,70,4,0,0,0,28,0,0,0,0,1,0,32,244,0,0,0,108,0,0,0,2,0,0,0,1,0,0,0,116,0,0,0,132,0,0,0,148,0,0,0,2,0,1,0,1,0,0,0,156,0,0,0,132,0,0,0,172,0,0,0,2,0,2,0,1,0,0,0,192,0,0,0,132,0,0,0,208,0,0,0,2,0,3,0,1,0,0,0,228,0,0,0,132,0,0,0,71,114,97,118,105,116,121,0,1,0,3,0,1,0,3,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,77,97,120,84,105,109,101,0,0,0,3,0,1,0,1,0,1,0,0,0,0,0,0,0,82,97,110,103,101,70,114,111,109,70,97,100,101,84,111,69,110,100,0,171,0,0,3,0,1,0,1,0,1,0,0,0,0,0,0,0,84,105,109,101,84,111,68,101,102,97,117,108,116,67,111,108,111,114,0,171,0,0,3,0,1,0,1,0,1,0,0,0,0,0,0,0,116,120,0,77,105,99,114,111,115,111,102,116,32,40,82,41,32,72,76,83,76,32,83,104,97,100,101,114,32,67,111,109,112,105,108,101,114,32,57,46,50,54,46,57,53,50,46,50,56,52,52,0,254,255,12,0,80,82,83,73,7,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,7,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,254,255,2,0,67,76,73,84,0,0,0,0,254,255,50,0,70,88,76,67,5,0,0,0,3,0,80,160,2,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,1,0,48,16,1,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,0,0,0,0,7,0,0,0,3,0,0,0,3,0,80,160,2,0,0,0,0,0,0,0,7,0,0,0,3,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,28,0,0,0,1,0,48,16,1,0,0,0,0,0,0,0,2,0,0,0,8,0,0,0,0,0,0,0,4,0,0,0,32,0,0,0,1,0,48,16,1,0,0,0,0,0,0,0,2,0,0,0,12,0,0,0,0,0,0,0,4,0,0,0,36,0,0,0,240,240,240,240,15,15,15,15,255,255,0,0,81,0,0,5,17,0,15,160,0,0,0,63,0,0,128,63,0,0,0,0,0,0,0,0,31,0,0,2,0,0,0,128,0,0,15,144,31,0,0,2,5,0,0,128,1,0,15,144,31,0,0,2,11,0,0,128,2,0,15,144,31,0,0,2,11,0,1,128,3,0,15,144,31,0,0,2,11,0,2,128,4,0,15,144,31,0,0,2,0,0,0,128,0,0,15,224,31,0,0,2,5,0,0,128,1,0,3,224,31,0,0,2,10,0,0,128,2,0,15,224,2,0,0,3,0,0,1,128,10,0,0,160,2,0,255,145,2,0,0,3,0,0,2,128,0,0,0,129,16,0,0,160,2,0,0,3,0,0,2,128,0,0,85,129,16,0,0,160,5,0,0,3,0,0,2,128,0,0,85,128,9,0,0,160,5,0,0,3,1,0,15,128,12,0,228,160,4,0,228,144,4,0,0,4,2,0,15,128,0,0,85,128,1,0,228,128,1,0,228,129,12,0,0,3,0,0,2,128,0,0,0,128,16,0,0,160,4,0,0,4,2,0,15,128,0,0,85,128,2,0,228,128,1,0,228,128,1,0,0,2,3,0,15,128,12,0,228,160,4,0,0,4,3,0,15,128,3,0,228,128,4,0,228,145,11,0,228,160,2,0,0,3,0,0,2,128,0,0,0,128,14,0,0,161,1,0,0,2,4,0,2,128,17,0,85,160,4,0,0,4,0,0,2,128,0,0,85,128,8,0,0,160,4,0,85,128,4,0,0,4,1,0,15,128,0,0,85,128,3,0,228,128,1,0,228,128,2,0,0,3,1,0,15,128,2,0,228,129,1,0,228,128,13,0,0,3,0,0,2,128,0,0,0,128,13,0,0,160,4,0,0,4,2,0,15,224,0,0,85,128,1,0,228,128,2,0,228,128,5,0,0,3,0,0,2,128,0,0,0,128,0,0,0,128,5,0,0,3,0,0,14,128,0,0,85,128,7,0,144,160,1,0,0,2,1,0,15,128,3,0,228,144,4,0,0,4,1,0,7,128,1,0,228,128,0,0,0,128,2,0,228,144,4,0,0,4,0,0,14,128,0,0,228,128,17,0,0,160,1,0,144,128,5,0,0,3,1,0,7,128,15,0,228,160,3,0,228,144,4,0,0,4,0,0,7,128,1,0,228,128,0,0,0,129,0,0,249,128,1,0,0,2,0,0,8,128,17,0,85,160,9,0,0,3,1,0,1,128,0,0,228,128,4,0,228,160,9,0,0,3,1,0,2,128,0,0,228,128,5,0,228,160,9,0,0,3,1,0,4,128,0,0,228,128,6,0,228,160,4,0,0,4,0,0,7,128,0,0,228,144,1,0,255,128,1,0,228,128,1,0,0,2,0,0,8,128,17,0,85,160,9,0,0,3,0,0,1,224,0,0,228,128,0,0,228,160,9,0,0,3,0,0,2,224,0,0,228,128,1,0,228,160,9,0,0,3,0,0,4,224,0,0,228,128,2,0,228,160,9,0,0,3,0,0,8,224,0,0,228,128,3,0,228,160,1,0,0,2,1,0,3,224,1,0,228,144,255,255,0,0,255,255,255,255,14,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,0,0,0,84,101,120,116,117,114,101,0 };
#endif


        /// <summary>
        /// Instantiates a new PhotonMainRenderer
        /// </summary>
        /// <param name="system"></param>
        public PhotonMainGPURenderer(ParticleEmitter emitter)
            : base(emitter)
        {
            Load();
            VertexPositionTexture[] vertices = new VertexPositionTexture[]
            {
                new VertexPositionTexture(
                                new Vector3(1,-1,0),
                                new Vector2(1,1)),
                new VertexPositionTexture(
                                new Vector3(-1,-1,0),
                                new Vector2(0,1)),
                new VertexPositionTexture(
                                new Vector3(-1,1,0),
                                new Vector2(0,0)),
                new VertexPositionTexture(
                                new Vector3(1,1,0),
                                new Vector2(1,0))
            };
            short[] indices = new short[] { 0, 1, 2, 2, 3, 0 };

            VertexBuffer ParticleVertexBuffer = new VertexBuffer(GraphicsDevice,
                VertexPositionTexture.VertexDeclaration, vertices.Length, BufferUsage.None);
            ParticleVertexBuffer.SetData(vertices);

            IndexBuffer ParticleIndexBuffer = new IndexBuffer(GraphicsDevice,
                IndexElementSize.SixteenBits, indices.Length, BufferUsage.None);
            ParticleIndexBuffer.SetData(indices);

            InstancingHelper = new InstancingSystem(ParticleVertexBuffer, ParticleIndexBuffer,
                instanceVertexDeclaration);

            emitter.Reserved_SpawnParticle += new SetIndexParticleNEmitter(system_Reserved_SpawnParticle);
        }

        void system_Reserved_SpawnParticle(int index, Particle p, ParticleEmitter emitter)
        {
            if (emitter.RenderingTag == null ||
                !(emitter.RenderingTag is PhotonGPUDataHolders))
            {
                emitter.RenderingTag = new PhotonGPUDataHolders();
            }
            PhotonGPUDataHolders data = emitter.RenderingTag as PhotonGPUDataHolders;
            if (data.ParticlesTransforms.Length < emitter.MaxParticles)
            {
                data.ParticlesTransforms = new PhotonParticleGPU[emitter.MaxParticles];
            }

            PhotonParticleGPU ph = new PhotonParticleGPU();
            ph.PositionTime = new Vector4(p.Position, (float)Engine.Instance.GameTime.TotalGameTime.TotalSeconds);
            ph.LinearVelocitySize = new Vector4(p.LinearVelocity, p.Size);
            ph.StartColor = p.Color.ToVector4();

            data.ParticlesTransforms[index] = ph;
        }

        /// <summary>
        /// Instantiates a new PhotonMainRenderer
        /// </summary>
        /// <param name="emitter"></param>
        /// <param name="meshVertexBuffer">A Vertex Buffer for rendering Particles as Custom Meshes</param>
        /// <param name="meshIndexBuffer">A Index Buffer for the last Vertex Buffer</param>
        public PhotonMainGPURenderer(ParticleEmitter emitter, VertexBuffer meshVertexBuffer, IndexBuffer meshIndexBuffer)
            : base(emitter)
        {
            Load();
            InstancingHelper = new InstancingSystem(meshVertexBuffer, meshIndexBuffer,
                instanceVertexDeclaration);
        }

        private void Load()
        {
            DepthStencilState = DepthStencilState.DepthRead;
            RasterizerState = RasterizerState.CullCounterClockwise;

            this.IsGPURenderer = true;
            this.CanHandleParticleUpdate = true;
            this.CPU_NeedsTransform = false;

            GraphicsDevice = Engine.Instance.GraphicsDevice;

#if !SILVERLIGHT
            Effect = new Effect(GraphicsDevice, effectBytes);
#else
            Effect = Engine.ContentManager.Load<SilverlightEffect>("Engine\\Effects\\fx_PhotonGPU");
#endif
        }

        /// <inheritdoc />
        public override void Draw()
        {
            GraphicsDevice.DepthStencilState = DepthStencilState;
            GraphicsDevice.RasterizerState = RasterizerState;

            DrawParticleEmmiter(this.ParticleEmitter);

            GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
        }

        /// <summary>
        /// Draws a Particle Emmiter
        /// </summary>
        /// <param name="emitter">The Particle Emmiter you want to draw</param>
        public virtual void DrawParticleEmmiter(ParticleEmitter emitter)
        {
            if (Engine.Instance.CameraManager.Camera3D != null)
            {
                ICamera3D Camera = Engine.Instance.CameraManager.Camera3D;

                GraphicsDevice.BlendState = emitter.Properties.BlendState;

                float CurrentTime = (float)Engine.Instance.GameTime.TotalGameTime.TotalSeconds;

                // 1 - Check if our Transforms array is big enough
                if (emitter.RenderingTag == null ||
                    !(emitter.RenderingTag is PhotonGPUDataHolders))
                {
                    emitter.RenderingTag = new PhotonGPUDataHolders();
                }
                PhotonGPUDataHolders data = emitter.RenderingTag as PhotonGPUDataHolders;
                if (data.ParticlesTransforms.Length < emitter.MaxParticles)
                {
                    data.ParticlesTransforms = new PhotonParticleGPU[emitter.MaxParticles];
                }

                // 2 - Check if there is a particle to render
                if (emitter.ActiveParticles == 0)
                {
                    return;
                }

                // 3 - Check for the Oldest Particle time, and if we should delete it
                PhotonParticleGPU particle = data.ParticlesTransforms[emitter.FirstActiveParticle];
                float time = CurrentTime - particle.PositionTime.W;
                if (time > emitter.Properties.MaxTime)
                {
                    emitter.RemoveParticle(emitter.FirstActiveParticle);
                }

                // 4 - Check if our Transforms Vertex Buffer is big enough
                InstancingHelper.ResizeBufferIfNotBig(emitter.MaxParticles);

                // 5 - Again, check if we have particles(after updating they may have ended)
                if (emitter.ActiveParticles == 0)
                {
                    return;
                }

                // 6 - Set the Transforms to the Instances Vertex Buffer
                bool sequence = true;
                if (emitter.LastActiveParticle - emitter.FirstActiveParticle <= 0)
                {
                    sequence = false;
                }

                // Particles are in sequence
                if (sequence)
                {
                    // Particles are in sequence
                    InstancingHelper.InstancesVertexBuffer.SetData(data.ParticlesTransforms, emitter.FirstActiveParticle, emitter.LastActiveParticle - emitter.FirstActiveParticle, SetDataOptions.None);
                }
                else
                {
                    int size = 48;
                    // No sequence =(
                    if (emitter.LastActiveParticle > 0)
                    {
                        InstancingHelper.InstancesVertexBuffer.SetData(data.ParticlesTransforms, 0, emitter.LastActiveParticle, SetDataOptions.None);
                    }
                    InstancingHelper.InstancesVertexBuffer.SetData(size * emitter.LastActiveParticle, data.ParticlesTransforms, emitter.FirstActiveParticle, emitter.MaxParticles - emitter.FirstActiveParticle, size, SetDataOptions.NoOverwrite);
                }

                // 7 - Set the Vertex Buffer to the Graphics Device
#if !SILVERLIGHT
                GraphicsDevice.SetVertexBuffers(
                    new VertexBufferBinding(InstancingHelper.ModelVertexBuffer, 0, 0),
                    new VertexBufferBinding(InstancingHelper.InstancesVertexBuffer, 0, 1)
                    );

                GraphicsDevice.Indices = InstancingHelper.ModelIndexBuffer;

                Effect.Parameters["View"].SetValue(Camera.View);
                Effect.Parameters["Projection"].SetValue(Camera.Projection);
                Effect.Parameters["World"].SetValue(Matrix.Identity);
                Effect.Parameters["Texture"].SetValue(emitter.Properties.Texture);

                Effect.Parameters["Gravity"].SetValue(emitter.Properties.Gravity);
                Effect.Parameters["CurrentTime"].SetValue(CurrentTime);

                Effect.Parameters["StartColor"].SetValue(emitter.Properties.StartColor.ToVector4());
                Effect.Parameters["EndColor"].SetValue(emitter.Properties.EndColor.ToVector4());

                Effect.Parameters["StartFadeTime"].SetValue(emitter.Properties.StartFadeOutTime);
                Effect.Parameters["MaxTime"].SetValue(emitter.Properties.MaxTime);

                Effect.Parameters["RangeFromFadeToEnd"].SetValue(emitter.Properties.DifferenceFromFadeOutToEnd);
                Effect.Parameters["LinearVelocityLoss"].SetValue(emitter.Properties.LinearVelocityLoss);

                Effect.Parameters["TimeToDefaultColor"].SetValue(emitter.Properties.TimeToDefaultColor);

                Effect.Parameters["AlphaClip"].SetValue(AlphaClip);

                // 8 - Render the Particle
                foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
                {
                    pass.Apply();

                    GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList,
                        0, 0, InstancingHelper.ModelVertexBuffer.VertexCount, 0, 2, emitter.ActiveParticles);
                }

                GraphicsDevice.SetVertexBuffer(null);
#endif
            }
        }

        public override float GetParticleTime(Particle p)
        {
            float time = (float)Engine.Instance.GameTime.TotalGameTime.TotalSeconds - p.AliveTime;
            return time;
        }

        public override Vector3 GetParticleCurrentPosition(Particle p)
        {
            float time = GetParticleTime(p);
            Vector3 linearVel = p.LinearVelocity + (p.Emitter.Properties.Gravity * time);
            linearVel = linearVel - (linearVel * p.Emitter.Properties.LinearVelocityLoss);

            Vector3 finalPos = p.Position + (linearVel * time);

            return finalPos;
        }
    }
#endif
}
